package api

import (
	"math"
	"net/http"
	"pids-cloud-server/app/common"
	"pids-cloud-server/constants"
	"pids-cloud-server/entity"
	"pids-cloud-server/entity/dto"
	"pids-cloud-server/logging"
	"pids-cloud-server/utils"
	"reflect"
	"strconv"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/goccy/go-json"
)

// UploadDataTask
// @Summary 上报采集数据
// @Description 上报采集数据
// @Tags 采集数据上报
// @Accept json
// @Produce json
// @Param paramdto body dto.ParamDto true "采集数据"
// @Success 200 {object} common.Result
// @Failure 400 {object} common.Result
// @Router /agent/minTask [post]
func UploadDataTask(c *gin.Context) {
	var paramdto dto.ParamDto
	db := utils.GetDB()
	if db == nil {
		common.ErrorResponse(c, http.StatusInternalServerError, "数据库连接失败")
		return
	}
	if err := c.BindJSON(&paramdto); err != nil {
		common.ErrorResponse(c, http.StatusBadRequest, err.Error())
		return
	}
	if paramdto.PidsToken == "" {
		common.ErrorResponse(c, http.StatusBadRequest, "PidsToken不能为空")
		return
	}
	// 校验 PidsToken
	if !utils.CheckToken(paramdto.PidsToken) {
		common.ErrorResponse(c, http.StatusForbidden, "PidsToken校验失败")
		return
	}

	cpuState := paramdto.CpuState
	memState := paramdto.MemState
	diskStateList := paramdto.DeskStateList
	systemInfo := paramdto.SystemInfo

	if !reflect.DeepEqual(cpuState, entity.CpuState{}) {
		cpuState.Type = systemInfo.Type
		cpustatejson, err := json.Marshal(cpuState)
		if err != nil {
			logging.Error("上报cpu状态序列化失败", err.Error())
		} else {
			utils.LPush(constants.CPU_STATE_LIST, cpustatejson)
		}
	}
	if !reflect.DeepEqual(memState, entity.MemState{}) {
		memState.Type = systemInfo.Type
		memstatejson, err := json.Marshal(memState)
		if err != nil {
			logging.Error("上报内存状态序列化失败", err.Error())
		} else {
			utils.LPush(constants.MEM_STATE_LIST, memstatejson)
		}
	}
	totalDiskState := entity.DeskState{}
	var (
		totalSize  float64
		totalUsed  float64
		totalAvail float64
	)
	if len(diskStateList) > 0 {
		totalDiskState.HostName = diskStateList[0].HostName
		totalDiskState.FileSystem = "/"
		totalDiskState.CreateTime = diskStateList[0].CreateTime

		for _, deskState := range diskStateList {
			if strings.Contains(deskState.Avail, "M") {
				continue
			}
			if size, err := strconv.ParseFloat(replaceArgs(deskState.Size, []string{"GB", "G"}, ""), 64); err == nil {
				totalSize += size
			}
			if size, err := strconv.ParseFloat(replaceArgs(deskState.Used, []string{"GB", "G"}, ""), 64); err == nil {
				totalUsed += size
			}
			if size, err := strconv.ParseFloat(replaceArgs(deskState.Avail, []string{"GB", "G"}, ""), 64); err == nil {
				totalAvail += size
			}
		}
		totalDiskState.Avail = strconv.FormatFloat(totalAvail, 'f', 2, 64) + "G"
		totalDiskState.Size = strconv.FormatFloat(totalSize, 'f', 2, 64) + "G"
		totalDiskState.Used = strconv.FormatFloat(totalUsed, 'f', 2, 64) + "G"
		totalDiskState.UsePer = math.Round(totalUsed / totalSize * 100)
		totalDiskState.Type = systemInfo.Type
		diskstatejson, err := json.Marshal(totalDiskState)
		if err != nil {
			logging.Error("上报磁盘状态序列化失败", err.Error())
		} else {
			utils.LPush(constants.DISK_STATE_LIST, diskstatejson)
		}
	}

	networkState := entity.NetworkState{}
	networkState.CreateTime = time.Now()
	networkState.HostName = systemInfo.HostName
	networkState.Status = systemInfo.NetworkState
	networkState.ID = utils.GenerateID().Int64()
	networkState.Type = systemInfo.Type
	networkstatejson, err := json.Marshal(networkState)
	if err != nil {
		logging.Error("网络状态序列化失败", err.Error())
	} else {
		utils.LPush(constants.NETWORK_STATE_LIST, networkstatejson)
	}
	if systemInfo.HostName == "" {
		common.ErrorResponse(c, http.StatusBadRequest, "HostName不能为空")
		return
	}
	if !reflect.DeepEqual(systemInfo, entity.SystemInfo{}) {
		// 移除强制设置 NetworkState = entity.ONLINE，保留客户端传入的值
		var oldsystemInfo entity.SystemInfo
		if db.Find(&oldsystemInfo, "host_name = ?", systemInfo.HostName); oldsystemInfo.HostName == "" {
			systemInfo.ID = utils.GenerateID().Int64()
			db.Create(&systemInfo)
		} else {
			systemInfo.ID = oldsystemInfo.ID
			db.Model(&systemInfo).Updates(map[string]interface{}{
				"version":         systemInfo.Version,
				"version_detail":  systemInfo.VersionDetail,
				"disk_total_size": totalSize,
				"disk_per":        totalDiskState.UsePer,
				"uptime":          systemInfo.Uptime,
				"mem_total_size":  systemInfo.MemTotalSize,
				"network_state":   systemInfo.NetworkState,
				"mem_per":         systemInfo.MemPer,
				"cpu_per":         systemInfo.CpuPer,
				"create_time":     time.Now(),
				"json":            systemInfo.Json,
				"type":            systemInfo.Type,
			})
		}
	} else {
		common.ErrorResponse(c, http.StatusBadRequest, "systemInfo不能为空")
		return
	}
	common.SuccessResponse(c, gin.H{})
}

func replaceArgs(s string, oldarr []string, new string) string {
	for _, old := range oldarr {
		s = strings.ReplaceAll(s, old, new)
	}
	return s
}
